﻿/* ----------------------------------------------------------------------------
 * Copyright (c) Philip Stears 
 *
 * This source code is subject to terms and conditions of the Microsoft Public 
 * License (Ms-PL).
 * 
 * By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 * 
 * To request a copy of the Microsoft Public License, send a request by email
 * to license@connectbasic.net.
 *
 * This notice must not be removed from this software.
 * ---------------------------------------------------------------------------- */

namespace ConnectBasic.ObjectModel
{
    using System;
    using System.Diagnostics;
    using ConnectBasic.Execution;
    using Microsoft.Scripting;
    using DlrExpression = Microsoft.Linq.Expressions.Expression;

    /// <summary>
    /// Represents a statement which assigns the result of an expression to a named target.
    /// </summary>
    [DebuggerDisplay("Assign {TargetName}={Expression}")]
    public class AssignStatement : StatementNodeBase
    {
        private readonly string mTargetName;
        private readonly ExpressionBase mExpression;
        private readonly SourceSpan mSpan;

        /// <summary>
        /// Initializes a new instance of the <see cref="AssignStatement" /> class.
        /// </summary>
        /// <param name="statementSpan">The span of the assignment in the source text.</param>
        /// <param name="targetName">The target of the assignment (might be null if this is an error node).</param>
        /// <param name="expression">The expression which provides the value to assign (might be null if this is an error node).</param>
        public AssignStatement(SourceSpan statementSpan, string targetName, ExpressionBase expression)
        {
            mSpan = statementSpan;
            mTargetName = targetName;
            mExpression = expression;
        }

        /// <summary>
        /// Gets the span of the assignment in the source text.
        /// </summary>
        public SourceSpan StatementSpan
        {
            get { return mSpan; }
        }

        /// <summary>
        /// Gets the name of the target.
        /// </summary>
        public string TargetName
        {
            get { return mTargetName; }
        }

        /// <summary>
        /// Gets the expression which provides the value to assign.
        /// </summary>
        public ExpressionBase Expression
        {
            get { return mExpression; }
        }

        /// <inheritdoc />
        public override DlrExpression Compile(BasicCodeGenerator gen)
        {

            // Get the current naming scope to create an assignment expression for us
            DlrExpression target =
                gen.Scope.MakeSetValueExpression(
                    mTargetName,
                    gen.MeParameter,
                    (targetType) => GeneratorUtil.Convert(this.Expression.Compile(gen), targetType));

            if (target == null)
            {
                throw new Exception("Target not found");
            }
            else
            {
                // If we've got debugging information, add it now
                target = gen.AddDebugInfo(target, mSpan);

                return target;
            }
        }
    }
}
